package com.practice.springboot_01_zwj.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.practice.springboot_01_zwj.entity.IncomeQuestion;
import com.practice.springboot_01_zwj.entity.PageRequest;
import com.practice.springboot_01_zwj.entity.PageResult;
import com.practice.springboot_01_zwj.mapper.IncomeQuestionMapper;
import com.practice.springboot_01_zwj.service.IncomeQuestionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.BiFunction;

@Service
@Transactional
public class IncomeQuestionServiceImpl implements IncomeQuestionService {
    @Autowired
    private IncomeQuestionMapper dao;


    @Override
    public List<IncomeQuestion> selectIncomeQuestionAll() {
        return dao.selectIncomeQuestionAll();
    }
    @Override
    public PageResult<IncomeQuestion> selectIncomeQuestionPage(PageRequest pageRequest) {
        PageHelper.startPage(pageRequest.getPageNum(), pageRequest.getPageSize());
        List<IncomeQuestion> list = dao.selectIncomeQuestionAll();
        PageInfo<IncomeQuestion> pageInfo = new PageInfo<>(list);

        return new PageResult<>(
                pageInfo.getPageNum(),      // int -> 自动装箱为Integer
                pageInfo.getPageSize(),     // int -> 自动装箱为Integer
                pageInfo.getTotal(),        // long -> 自动装箱为Long
                pageInfo.getList()          // List<IncomeQuestion>
        );
    }
    @Override
    public Map<String, Object> selectIncomeByCityCode(String cityCode,String yearFilter) {
        return dao.selectIncomeByCityCode(cityCode,yearFilter);
    }

    @Override
    public Map<String, Object> selectIncomeByProvinceCode(String provinceCode,String yearFilter) {
        return dao.selectIncomeByProvinceCode(provinceCode,yearFilter);
    }

    @Override
    public Map<String, Object> selectMgrByCityCode(String cityCode,String yearFilter) {
        return dao.selectMgrByCityCode(cityCode,yearFilter);
    }

    @Override
    public Map<String, Object> selectMgrByProvinceCode(String provinceCode,String yearFilter) {
        return dao.selectMgrByProvinceCode(provinceCode,yearFilter);
    }

    @Override
    public Map<String, Object> selectQuestionByCityCode(String cityCode,String yearFilter) {
        return dao.selectQuestionByCityCode(cityCode,yearFilter);
    }

    @Override
     public Map<String, Object> selectQuestionByProvinceCode(String provinceCode,String yearFilter) {
        return dao.selectQuestionByProvinceCode(provinceCode,yearFilter);
    }

    @Override
    public PageResult<IncomeQuestion> selectProvinceTotalIncomePage(
            String provinceCode,
            IncomeQuestion condition,
            PageRequest pageRequest) {

        // 1. 获取全部数据（根据条件过滤）
        List<IncomeQuestion> allData = dao.selectProvinceTotalIncome(
                provinceCode, condition);

        // 2. 执行内存分页
        return paginateData(allData, pageRequest);
    }

    @Override
    public PageResult<IncomeQuestion> selectCityTotalIncomePage(
            String cityCode,
            IncomeQuestion condition,
            PageRequest pageRequest) {

        // 1. 获取全部数据（根据条件过滤）
        List<IncomeQuestion> allData = dao.selectCityTotalIncome(
                cityCode, condition);

        // 2. 执行内存分页
        return paginateData(allData, pageRequest);
    }

    // 通用的内存分页方法
    private PageResult<IncomeQuestion> paginateData(
            List<IncomeQuestion> allData,
            PageRequest pageRequest) {

        int pageNum = pageRequest.getPageNum();
        int pageSize = pageRequest.getPageSize();
        int totalItems = allData.size();

        // 计算总页数
        int totalPages = (totalItems + pageSize - 1) / pageSize;

        // 确保当前页在有效范围内
        if (pageNum > totalPages) {
            pageNum = totalPages;
        }
        if (pageNum < 1) {
            pageNum = 1;
        }

        // 计算分页起始位置
        int startIndex = (pageNum - 1) * pageSize;
        if (startIndex < 0) startIndex = 0;

        // 处理空数据集情况
        if (startIndex >= totalItems) {
            return new PageResult<>(
                    pageNum,
                    pageSize,
                    (long) totalItems,
                    Collections.emptyList()
            );
        }

        // 计算结束位置
        int endIndex = Math.min(startIndex + pageSize, totalItems);

        // 获取当前页数据
        List<IncomeQuestion> pageData = allData.subList(startIndex, endIndex);

        return new PageResult<>(
                pageNum,
                pageSize,
                (long) totalItems,
                pageData
        );
    }

    @Override
    public List<IncomeQuestion> selectCityCollection() {
        return dao.selectCityCollection();
    }


    // 操作类型枚举
    private enum OperationType {
        ZT_PRO, YJX_PRO, XS_SHANG_JI, DY_LX_PRO, YL_PRO_NONE,
        ZB_DLX, LX_DQY, JF_DYS, YQ_PRO, YQ_JD_PRO, YQ_JF_PRO,
        FJ_PRO, JT_BZ, CZ_JF
    }

    // DAO方法映射表
    private final Map<OperationType, Map<AreaType, BiFunction<String, IncomeQuestion, List<IncomeQuestion>>>> daoMethodMap = new HashMap<>();

    public IncomeQuestionServiceImpl(IncomeQuestionMapper dao) {
        this.dao = dao;
        initDaoMethodMap();
    }

    private void initDaoMethodMap() {
        // 初始化在途项目
        addOperation(OperationType.ZT_PRO, AreaType.PROVINCE, dao::selectProvinceZtPro);
        addOperation(OperationType.ZT_PRO, AreaType.CITY, dao::selectCityZtPro);

        // 初始化已结项项目
        addOperation(OperationType.YJX_PRO, AreaType.PROVINCE, dao::selectProvinceYjxPro);
        addOperation(OperationType.YJX_PRO, AreaType.CITY, dao::selectCityYjxPro);

        // 初始化线索商机
        addOperation(OperationType.XS_SHANG_JI, AreaType.PROVINCE, dao::selectProvinceXsShangJi);
        addOperation(OperationType.XS_SHANG_JI, AreaType.CITY, dao::selectCityXsShangJi);

        // 待预立项项目
        addOperation(OperationType.DY_LX_PRO, AreaType.PROVINCE, dao::selectProvinceDyLxPro);
        addOperation(OperationType.DY_LX_PRO, AreaType.CITY, dao::selectCityDyLxPro);

        // 预立项未中标
        addOperation(OperationType.YL_PRO_NONE, AreaType.PROVINCE, dao::selectProvinceYlProNone);
        addOperation(OperationType.YL_PRO_NONE, AreaType.CITY, dao::selectCityYlProNone);

        // 中标待立项
        addOperation(OperationType.ZB_DLX, AreaType.PROVINCE, dao::selectProvinceZbDlx);
        addOperation(OperationType.ZB_DLX, AreaType.CITY, dao::selectCityZbDlx);

        // 立项待签约
        addOperation(OperationType.LX_DQY, AreaType.PROVINCE, dao::selectProvinceLxDqy);
        addOperation(OperationType.LX_DQY, AreaType.CITY, dao::selectCityLxDqy);

        // 交付待验收
        addOperation(OperationType.JF_DYS, AreaType.PROVINCE, dao::selectProvinceJfDys);
        addOperation(OperationType.JF_DYS, AreaType.CITY, dao::selectCityJfDys);

        // 逾期签约项目
        addOperation(OperationType.YQ_PRO, AreaType.PROVINCE, dao::selectProvinceYqPro);
        addOperation(OperationType.YQ_PRO, AreaType.CITY, dao::selectCityYqPro);

        // 逾期交底项目
        addOperation(OperationType.YQ_JD_PRO, AreaType.PROVINCE, dao::selectProvinceYqJdPro);
        addOperation(OperationType.YQ_JD_PRO, AreaType.CITY, dao::selectCityYqJdPro);

        // 逾期交付
        addOperation(OperationType.YQ_JF_PRO, AreaType.PROVINCE, dao::selectProvinceYqJfPro);
        addOperation(OperationType.YQ_JF_PRO, AreaType.CITY, dao::selectCityYqJfPro);

        // 预立项超30天未中标
        addOperation(OperationType.FJ_PRO, AreaType.PROVINCE, dao::selectProvinceFjPro);
        addOperation(OperationType.FJ_PRO, AreaType.CITY, dao::selectCityFjPro);

        // 未按计划计提报账
        addOperation(OperationType.JT_BZ, AreaType.PROVINCE, dao::selectProvinceJtBz);
        addOperation(OperationType.JT_BZ, AreaType.CITY, dao::selectCityJtBz);

        // 未按计划出账计费
        addOperation(OperationType.CZ_JF, AreaType.PROVINCE, dao::selectProvinceCzJf);
        addOperation(OperationType.CZ_JF, AreaType.CITY, dao::selectCityCzJf);
    }

    private void addOperation(OperationType operation, AreaType areaType,
                              BiFunction<String, IncomeQuestion, List<IncomeQuestion>> function) {
        daoMethodMap.computeIfAbsent(operation, k -> new HashMap<>())
                .put(areaType, function);
    }

    @Override
    public PageResult<IncomeQuestion> selectByOperation(
            String operationType,
            String areaCode,
            AreaType areaType,
            IncomeQuestion condition,
            PageRequest pageRequest) {

        // 转换操作类型字符串为枚举
        OperationType operation = OperationType.valueOf(operationType);

        // 创建条件副本，避免修改原始对象
        IncomeQuestion finalCondition = Optional.ofNullable(condition)
                .map(IncomeQuestion::clone)
                .orElseGet(IncomeQuestion::new);

        // 处理年份筛选：线索商机(XS_SHANG_JI)使用 oppcreatedate 字段进行筛选
        if (operation == OperationType.XS_SHANG_JI) {
            applyOppCreateDateFilter(finalCondition);
        } else {
            // 其他操作使用 preProjectDate 字段进行筛选
            applyPreProjectDateFilter(finalCondition);
        }

        // 获取对应的DAO方法
        BiFunction<String, IncomeQuestion, List<IncomeQuestion>> daoMethod =
                Optional.ofNullable(daoMethodMap.get(operation))
                        .map(map -> map.get(areaType))
                        .orElseThrow(() -> new IllegalArgumentException("不支持的操作类型: " + operationType));

        // 执行DAO方法获取数据
        List<IncomeQuestion> allData = daoMethod.apply(areaCode, finalCondition);

        // 执行内存分页
        return paginateData(allData, pageRequest);
    }

    // 为线索商机(XS_SHANG_JI)应用 oppcreatedate 筛选
    private void applyOppCreateDateFilter(IncomeQuestion condition) {
        if (condition.getYearFilter() == null) return;

        switch (condition.getYearFilter()) {
            case "2023":
                condition.setBeginOppCreateDate("2023-01-01");
                condition.setEndOppCreateDate("2023-12-31");
                break;
            case "2024":
                condition.setBeginOppCreateDate("2024-01-01");
                condition.setEndOppCreateDate("2024-12-31");
                break;
            case "2025":
                condition.setBeginOppCreateDate("2025-01-01");
                condition.setEndOppCreateDate("2025-12-31");
                break;
            default:
                // "all" 或无效值时不设置日期范围
                condition.setBeginOppCreateDate(null);
                condition.setEndOppCreateDate(null);
        }
    }

    // 为其他操作应用 preProjectDate 筛选
    private void applyPreProjectDateFilter(IncomeQuestion condition) {
        if (condition.getYearFilter() == null) return;

        switch (condition.getYearFilter()) {
            case "2023":
                condition.setBeginPreProjectDate("2023-01-01");
                condition.setEndPreProjectDate("2023-12-31");
                break;
            case "2024":
                condition.setBeginPreProjectDate("2024-01-01");
                condition.setEndPreProjectDate("2024-12-31");
                break;
            case "2025":
                condition.setBeginPreProjectDate("2025-01-01");
                condition.setEndPreProjectDate("2025-12-31");
                break;
            default:
                // "all" 或无效值时不设置日期范围
                condition.setBeginPreProjectDate(null);
                condition.setEndPreProjectDate(null);
        }
    }
//    public PageResult<IncomeQuestion> selectByOperation(
//            String operationType,
//            String areaCode,
//            AreaType areaType,
//            IncomeQuestion condition,
//            PageRequest pageRequest) {
//
//        // 转换操作类型字符串为枚举
//        OperationType operation = OperationType.valueOf(operationType);
//
//        // 创建条件副本，避免修改原始对象
//        IncomeQuestion finalCondition = Optional.ofNullable(condition)
//                .map(IncomeQuestion::clone)
//                .orElseGet(IncomeQuestion::new);
//
//        // 处理年份筛选：XS_SHANG_JI 不需要年份筛选
//        if (operation != OperationType.XS_SHANG_JI) {
//            applyYearFilter(finalCondition);
//        } else {
//            // 清除日期范围条件
//            finalCondition.setBeginPreProjectDate(null);
//            finalCondition.setEndPreProjectDate(null);
//        }
//
//        // 获取对应的DAO方法
//        BiFunction<String, IncomeQuestion, List<IncomeQuestion>> daoMethod =
//                Optional.ofNullable(daoMethodMap.get(operation))
//                        .map(map -> map.get(areaType))
//                        .orElseThrow(() -> new IllegalArgumentException("不支持的操作类型: " + operationType));
//
//        // 执行DAO方法获取数据
//        List<IncomeQuestion> allData = daoMethod.apply(areaCode, finalCondition);
//
//        // 执行内存分页
//        return paginateData(allData, pageRequest);
//    }

    // 添加年份筛选处理方法
    private void applyYearFilter(IncomeQuestion condition) {
        if (condition.getYearFilter() == null) return;

        switch (condition.getYearFilter()) {
            case "2023":
                condition.setBeginPreProjectDate("2023-01-01");
                condition.setEndPreProjectDate("2023-12-31");
                break;
            case "2024":
                condition.setBeginPreProjectDate("2024-01-01");
                condition.setEndPreProjectDate("2024-12-31");
                break;
            case "2025":
                condition.setBeginPreProjectDate("2025-01-01");
                condition.setEndPreProjectDate("2025-12-31");
                break;
            default:
                // "all" 或无效值时不设置日期范围
                condition.setBeginPreProjectDate(null);
                condition.setEndPreProjectDate(null);
        }
    }

    @Override
    public List<IncomeQuestion> selectProvinceTotalIncomeAll(String provinceCode, IncomeQuestion condition) {
        if (condition == null) {
            condition = new IncomeQuestion();
        }
        return dao.selectProvinceTotalIncome(provinceCode, condition);
    }

    @Override
    public List<IncomeQuestion> selectCityTotalIncomeAll(String cityCode, IncomeQuestion condition) {
        if (condition == null) {
            condition = new IncomeQuestion();
        }
        return dao.selectCityTotalIncome(cityCode, condition);
    }
}
